/*
===========================================================================
This source file is part of DyLab (Dynamic Laboratory)
For the latest info, see http://code.google.com/p/dylab/

Copyright (c) 2006-2008 Lukas Krejci
(krejci.lukas@volny.cz)

This file is part of DyLab.

    DyLab is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    DyLab is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with DyLab.  If not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/

//===========================================================================================
#include <fstream>

//===========================================================================================
#include <dylab/utils/exceptions/EOperationFailed.h>
#include <dylab/utils/geometry/Vector3.h>
#include <dylab/utils/types/TypeParser.h>
#include <dylab/utils/formats/WavefrontObjFormat.h>

//===========================================================================================
dylab::WavefrontObjFormat::WavefrontObjFormat(IDataConsumer * _dataConsumer)
: mDataConsumer(_dataConsumer)
{ 
    DYLAB_ASSERT(mDataConsumer != NULL); 
}
//-----------------------------------------------------------------------------
dylab::WavefrontObjFormat::~WavefrontObjFormat()
{
}
//-----------------------------------------------------------------------------
void dylab::WavefrontObjFormat::parseFile(const String & _fileName)
{
    // open box definition text file
	std::ifstream f;	
	f.open (_fileName.c_str());
	if (f.fail())	        
        throw EOperationFailed(String::fmt("Can't open file: %1%", _fileName));		
			
    // vertex attribute indices
    uint32_t vertexNormalIndex = 0;
    uint32_t vertexTextureIndex = 0;
    real_t   x, y, z;
    uint32_t a, b, c;

    // read the file line by line
	char buffer[256];
	while (f.getline(buffer, 256).gcount () > 0)
	{
        // parse the current line
	    TokenParser tokenParser(buffer, "\t ,");

        // traverse through all line tokens
		for (TokenParser::Tokens::Iterator token(tokenParser.getTokens()); token.isValid(); ) 
        {            			
            if (token() == "v") // create vertex
            {	token++;				
                x = TypeParser::parse<real_t>(token()); token++;
                y = TypeParser::parse<real_t>(token()); token++;
                z = TypeParser::parse<real_t>(token()); token++;
                mDataConsumer->onCreateVertex(Vector3(x, y, z));
            }
            else if (token() == "vn") // set vertex normal
            {	token++;
                x = TypeParser::parse<real_t>(token()); token++;
                y = TypeParser::parse<real_t>(token()); token++;
                z = TypeParser::parse<real_t>(token()); token++;
                mDataConsumer->onSetVertexNormal(vertexNormalIndex++, Vector3(x, y, z));
            }
            else if (token() == "vt") // set vertex texture
            {	token++;
                x = TypeParser::parse<real_t>(token()); token++;
                y = TypeParser::parse<real_t>(token(), DYLAB_R(0)); token++;
                z = TypeParser::parse<real_t>(token(), DYLAB_R(0)); token++;
                mDataConsumer->onSetVertexTexture(vertexTextureIndex++, x, y, z);
            }
            else if (token() == "f") // create face (triangles are expected!)
            {	token++;
                a = TypeParser::parse<uint32_t>(String::getFirstLeftPart(token(), "/")) - 1; token++;
                b = TypeParser::parse<uint32_t>(String::getFirstLeftPart(token(), "/")) - 1; token++;
                c = TypeParser::parse<uint32_t>(String::getFirstLeftPart(token(), "/")) - 1; token++;
                mDataConsumer->onCreateFace(a, b, c);
            }
        }
    }
}
//-----------------------------------------------------------------------------